#include "BestQuoteFilterContainer.h"

#include <bondlib/QBIssuerInfo.h>
#include <core/StyleMgr.h>
#include <widgets/KeySearchWidget.h>

#include <QFile>
#include <QScrollArea>
#include <QVBoxLayout>

#include "../../BondSearch.h"
#include "BestQuoteFilter.h"

namespace {
const int lineHeight = 24;
const int gap = 4;
}  // namespace

class BondFilterSearchEngine : public MainSearchEngine {
 public:
  void setFilterWnd(BestQuoteFilterContainer* filter) { m_filter = filter; }
  virtual void onResultSelected(const QString& key) override {
    QB_CHECK_RETURN_VOID1(m_filter);
    QByteArray result = key.toLatin1();
    const char* sResult = result.data();

    QString strResult(sResult);
    QStringList strList = strResult.split('|');
    if (strList.size() > 2 && strList[0] == "data" && strList[1] == "issuer") {
      const IssuerInfo* pInfo =
          CQBIssuerInfo::instance().GetIssuerInfoByIndex(strList[2].toInt());
      if (pInfo && m_filter) {
        m_filter->setIssuerSearchResult(pInfo);
      }
    } else {
      int bondIndex = CBondContainer::instance().GetBondIndex(sResult);
      if (CBondContainer::instance().IsValidIndex(bondIndex)) {
        m_filter->setBondSearchResult(bondIndex, sResult);
      }
    }
  }

  virtual bool OnResult(const int* ids, int ncount, const char* key,
                        int len) override {
    int resCount = 0;
    CBondContainer::ScopedLock lock(CBondContainer::instance());
    int bond_count = CBondContainer::instance().GetSize();

    QJsonArray results;
    matchIssuers(key, 4, results);

    do {
      if (nullptr == ids || ncount <= 0) break;
      std::vector<int> bonds;
      bonds.reserve(ncount);
      CBondContainer& bc = CBondContainer::instance();
      for (int i = 0; i < ncount; i++) {
        int bid = qb::base::spell::getkey(ids[i]);
        if (!bc.IsValidIndex(bid)) continue;
        const CBondInfo& bi = bc.ElementAtR(bid);
        if (bi.IsExpireBond()) continue;
        if (bi.IsAddIssueBond()) continue;
        bonds.push_back(bid);
      }
      if (bonds.size() <= 0) break;

      const std::vector<int>& ids_results = SortResults(&bonds[0], ncount);
      ncount = ids_results.size();
      if (ncount > 0) {
        QJsonArray result;
        QString str("title|bond");
        result.push_back(str);
        result.push_back("债券");
        results.push_back(result);
      }

      // 优先判定是否均为数字
      bool bIsAllNumber = IsStringNumber(key);
      for (int i = 0; i < ncount; i++) {
        int bid = ids_results[i];
        if (bid < 0 || bid >= bond_count) continue;
        const CBondInfo& bi = CBondContainer::instance().ElementAtR(bid);
        if (bi.IsValidBond() && isMatch(bi, key, len, bIsAllNumber)) {
          QJsonArray result;
          QString str = QString::fromLocal8Bit(bi.GetCombBondKey());
          result.push_back(str);

          str = QString::fromLocal8Bit(bi.GetBondCode());
          if (str.isEmpty()) str = QStringLiteral("--");
          result.push_back(str);

          str = QString::fromLocal8Bit(bi.GetBondShortName());
          if (str.isEmpty()) str = QStringLiteral("--");
          result.push_back(str);

          str = QString::fromLocal8Bit(bi.GetIssuerBondRating());
          if (str.isEmpty()) str = QStringLiteral("--");
          result.push_back(str);

          str = QString::fromLocal8Bit(bi.GetRemainDate());
          if (str.isEmpty()) str = QStringLiteral("--");
          result.push_back(str);

          results.push_back(result);
          resCount++;
          if (resCount >= 100) {
            break;
          }
        }
      }
    } while (0);

    {
      std::lock_guard<std::mutex> locker(m_lock);
      QString keyStr = QString::fromLocal8Bit(key);
      if (/*resCount > 0 && */ m_searchHis[keyStr] == m_curSearchSerialNum)
        m_fun(m_curSearchSerialNum, results);
      m_searchHis.erase(keyStr);
    }

    return true;
  }

 private:
  BestQuoteFilterContainer* m_filter;
};

BestQuoteFilterContainer::BestQuoteFilterContainer(QWidget* parent)
    : QFrame(parent) {
  QString style =
      QString("QFrame {background-color:#%1;border:none;border-radius:2px;}")
          .arg(StyleMgr::instance().color("BasicPlate").rgb(), 0, 16);
  setStyleSheet(style);

  QVBoxLayout* mainLayout = new QVBoxLayout(this);
  mainLayout->setSpacing(gap);
  mainLayout->setContentsMargins(gap, 0, gap, 0);

  m_search = new KeySearchWidget(this, "SearchBackNormal2", "Hover",
                                 "TipsBorder", 0, true, 20, 9);
  BondFilterSearchEngine* engine = new BondFilterSearchEngine();
  engine->setFilterWnd(this);
  m_search->setAutoSelect(false);
  m_search->setAutoKillFocus(true);
  m_search->setEditFocusChangedClearText(false);
  m_search->setSearchEngine(engine);
  m_search->setFixedHeight(lineHeight);
  m_search->setResultDlgMinWidth(380);
  m_search->setResultDlgMaxHeight(20 * 8);
  m_search->setColumnsWidth(4, 120, 120, 80, 50);
  m_search->setPromptText(tr("搜索债券代码、简称和发行人"));

  QHBoxLayout* subLayout = new QHBoxLayout(this);
  subLayout->setContentsMargins(4, 0, 12, 0);
  subLayout->addWidget(m_search);

  QFrame* frame = new QFrame(this);
  m_filter = new BestQuoteFilter(frame);
  m_scrollArea = new QScrollArea(frame);
  m_scrollArea->setWidgetResizable(true);
  m_scrollArea->setWidget(m_filter);

  mainLayout->addLayout(subLayout);
  mainLayout->addWidget(frame);
  setLayout(mainLayout);

  connect(m_search, &KeySearchWidget::resultClear, this,
          &BestQuoteFilterContainer::onResultClear);
}

BestQuoteFilterContainer::~BestQuoteFilterContainer() {}

FilterCondition& BestQuoteFilterContainer::getFilterCondition() {
  return m_filter->getFilterCondition();
}

void BestQuoteFilterContainer::resizeEvent(QResizeEvent* event) {
  QRect r = rect();
  r.setWidth(r.width() - 8);
  m_scrollArea->setGeometry(r);  // docking button
}

void BestQuoteFilterContainer::setBondSearchResult(int bondIndex,
                                                   const char* bondKey) {
  FilterCondition& fc = m_filter->getFilterCondition();
  fc.nSearchType = 1;
  fc.strSearch = bondKey;
  fc.m_nFocusType = 0;
  fc.strGroupID.clear();

  emit filterChange();

  if (m_search) {
    const CBondInfo& bi = CBondContainer::instance().ElementAtR(bondIndex);
    m_search->setSearchText(bi.GetCombBondCode(), true);
    m_search->setEditFocus();
  }
}

void BestQuoteFilterContainer::setIssuerSearchResult(const StringArray* pInfo) {
  m_filter->setIssuerSearchResult(pInfo, false);

  if (m_search && pInfo) {
    IssuerInfo* issuerInfo = (IssuerInfo*)pInfo;
    m_search->setSearchText(QString::fromLocal8Bit(issuerInfo->field(
                                (int)kIssuerInfo::Full_Name_C)),
                            true);
    m_search->setEditFocus();
  }
}

void BestQuoteFilterContainer::onResultClear() {
  FilterCondition& fc = m_filter->getFilterCondition();
  fc.nSearchType = 0;
  fc.strSearch.clear();
  fc.m_nFocusType = 0;
  fc.strGroupID.clear();

  setIssuerSearchResult(nullptr);

  if (m_search) {
    m_search->setSearchText("");
  }
}
